package com.luo.chengrui.module.sa.service.commontree;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.luo.chengrui.module.sa.controller.admin.commontree.vo.CommonTreeBizCreateReqVO;
import com.luo.chengrui.module.sa.controller.admin.commontree.vo.CommonTreeBizExportReqVO;
import com.luo.chengrui.module.sa.controller.admin.commontree.vo.CommonTreeBizPageReqVO;
import com.luo.chengrui.module.sa.controller.admin.commontree.vo.CommonTreeBizUpdateReqVO;
import com.luo.chengrui.module.sa.convert.commontree.CommonTreeBizConvert;
import com.luo.chengrui.module.sa.dal.dataobject.commontree.CommonTreeBizDO;
import com.luo.chengrui.module.sa.dal.mysql.commontree.CommonTreeBizMapper;
import com.luo.chengrui.module.sa.service.commontree.CommonTreeBizService;
import com.luo.chengrui.module.sa.service.commontree.CommonTreeService;
import com.google.common.annotations.VisibleForTesting;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.luo.chengrui.module.sa.enums.ErrorCodeConstants.*;;

/**
 * 业务树 业务端通用树结构，必须与SA_COMMON_TREE表数据合并使用 Service 实现类
 *
 * @author 诚睿
 */
@Service
@Validated
public class CommonTreeBizServiceImpl implements CommonTreeBizService {

    @Resource
    private CommonTreeBizMapper commonTreeBizMapper;

    @Override
    public String createCommonTreeBiz(CommonTreeBizCreateReqVO createReqVO) {
        // 插入
        CommonTreeBizDO commonTreeBiz = CommonTreeBizConvert.INSTANCE.convert(createReqVO);
        validateForCreateOrUpdate(commonTreeBiz);
        commonTreeBizMapper.insert(commonTreeBiz);
        // 返回
        return commonTreeBiz.getId();
    }

    @Override
    public void updateCommonTreeBiz(CommonTreeBizUpdateReqVO updateReqVO) {
        // 校验自己存在
        validateCommonTreeBizExists(updateReqVO.getId());
        // 更新
        CommonTreeBizDO updateObj = CommonTreeBizConvert.INSTANCE.convert(updateReqVO);
        // 校验存在
        validateForCreateOrUpdate(updateObj);
        commonTreeBizMapper.updateById(updateObj);
    }

    @Override
    public void deleteCommonTreeBiz(String id) {
        // 校验存在
        validateCommonTreeBizExists(id);
        // 删除
        commonTreeBizMapper.deleteById(id);
    }

    private void validateForCreateOrUpdate(CommonTreeBizDO commonTreeBiz) {

        // 校验父部门的有效性
        validateParent(commonTreeBiz);
        // 校验部门名的唯一性
        validateNameUnique(commonTreeBiz);
        validateCodeUnique(commonTreeBiz);
    }

    @VisibleForTesting
    private void validateParent(CommonTreeBizDO commonTreeBiz) {
        if (commonTreeBiz.getParentId() == null) {
            throw exception(COMMON_TREE_PARENT_IS_NOT_NULL);
        }
        // 不能设置自己为父部门
        if (commonTreeBiz.getParentId().equals(commonTreeBiz.getId())) {
            throw exception(COMMON_TREE_PARENT_PARENT_ERROR);
        }
        // 父节点不存在
        CommonTreeBizDO parentNode = commonTreeBizMapper.selectByParentId(commonTreeBiz);
        if (parentNode == null) {
            throw exception(COMMON_TREE_PARENT_IS_NOT_NULL);
        }

    }

    @VisibleForTesting
    private void validateNameUnique(CommonTreeBizDO commonTreeBiz) {
        CommonTreeBizDO dept = commonTreeBizMapper.selectByParentIdAndName(commonTreeBiz);
        if (dept == null) {
            return;
        }
        // 如果 id 为空
        if (commonTreeBiz.getId() == null) {
            throw exception(COMMON_TREE_NAME_EXISTS);
        }
        if (ObjectUtil.notEqual(dept.getId(), commonTreeBiz.getId())) {
            throw exception(COMMON_TREE_NAME_EXISTS);
        }
    }

    @VisibleForTesting
    private void validateCodeUnique(CommonTreeBizDO commonTreeBiz) {
        CommonTreeBizDO treeNode = commonTreeBizMapper.selectByCode(commonTreeBiz);
        if (treeNode == null) {
            return;
        }
        if (commonTreeBiz.getId() == null) {
            throw exception(COMMON_TREE_CODE_EXISTS);
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的岗位
        if (!Objects.equals(commonTreeBiz.getId(), treeNode.getId())) {
            throw exception(COMMON_TREE_CODE_EXISTS);
        }

    }

    private void validateCommonTreeBizExists(String id) {
        if (commonTreeBizMapper.selectById(id) == null) {
            throw exception(COMMON_TREE_NOT_EXISTS);
        }
    }

    @Override
    public CommonTreeBizDO getCommonTreeBiz(String id) {
        return commonTreeBizMapper.selectById(id);
    }

    @Override
    public List<CommonTreeBizDO> getCommonTreeBizList(Collection<String> ids) {
        return commonTreeBizMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<CommonTreeBizDO> getCommonTreeBizPage(CommonTreeBizPageReqVO pageReqVO) {
        return commonTreeBizMapper.selectPage(pageReqVO);
    }

    @Override
    public List<CommonTreeBizDO> getCommonTreeBizList(CommonTreeBizExportReqVO exportReqVO) {
        return commonTreeBizMapper.selectList(exportReqVO);
    }

    @Override
    public List<CommonTreeBizDO> getChildrenBy(String id) {
        CommonTreeBizExportReqVO reqVO = new CommonTreeBizExportReqVO();
        List<CommonTreeBizDO> resultList = new ArrayList<>();
        reqVO.setParentId(id);
        if (StrUtil.isBlank(id)) {
            CommonTreeBizDO root = new CommonTreeBizDO();
            root.setName("根节点");
            root.setId(com.luo.chengrui.module.sa.service.commontree.CommonTreeService.COMMON_TREE_ROOT);
            root.setCode(CommonTreeService.COMMON_TREE_ROOT);
            resultList.add(root);
            return (resultList);
        }
        return commonTreeBizMapper.selectList(reqVO);
    }

    @Override
    public List<CommonTreeBizDO> getCommonTreeAllList(CommonTreeBizExportReqVO exportReqVO) {
        return commonTreeBizMapper.selectList(exportReqVO);
    }

}
